package com.ruoyi.system.utils;

import com.ruoyi.common.enums.UppercaseNumber;
import com.ruoyi.system.domain.vo.SysWhitePaperOutlineVo;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Component
public class PdfBoxGenerator {

    // 优化间距设置
    private static final float PAGE_MARGIN = 50;
    private static final float LINE_HEIGHT = 1.4f;
    private static final float CHAPTER_SPACING = 30;  // 章节标题上下间距
    private static final float TITLE_SPACING = 20;     // 小节标题上下间距
    private static final float CONTENT_SPACING = 20;   // 内容上下间距
    private static final float SECTION_SPACING = 40;  // 章节间间距
    private static final float SAFETY_MARGIN = 10;
    private static final float MIN_PAGE_HEIGHT = 80;

    public byte[] createSimplePdf(List<SysWhitePaperOutlineVo> whitePaperOutlineVoList) throws IOException {
        if (whitePaperOutlineVoList == null || whitePaperOutlineVoList.isEmpty()) {
            throw new IllegalArgumentException("白皮书数据不能为空");
        }

        try (PDDocument document = new PDDocument();
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

            PDFont chineseFont = getChineseFont(document);
            PageContext pageContext = new PageContext(document);

            try {
                Map<Long, List<SysWhitePaperOutlineVo>> outlineMap = whitePaperOutlineVoList.stream()
                        .collect(Collectors.groupingBy(SysWhitePaperOutlineVo::getChapterId));
                Set<Long> chapterIdSet = outlineMap.keySet();

                int chapterIndex = 0;
                for (Long chapterId : chapterIdSet) {
                    List<SysWhitePaperOutlineVo> tempList = outlineMap.get(chapterId);
                    if (tempList == null || tempList.isEmpty()) {
                        continue;
                    }

                    String chapterName = tempList.get(0).getChapterName();
                    if (chapterName == null) {
                        chapterName = "未命名章节";
                    }

                    // 检查章节标题是否需要新页面
                    String chapterText = UppercaseNumber.getDescByCode(chapterIndex + 1) + "，" + chapterName;
                    float chapterHeight = estimateTextHeight(chineseFont, 20, chapterText,
                            pageContext.getPageWidth() - 2 * PAGE_MARGIN - SAFETY_MARGIN) + CHAPTER_SPACING;

                    // 如果是新章节且不是第一页，添加章节间距
                    if (chapterIndex > 0) {
                        if (pageContext.getCurrentY() - SECTION_SPACING - chapterHeight < PAGE_MARGIN + MIN_PAGE_HEIGHT) {
                            pageContext.newPage();
                        } else {
                            pageContext.setCurrentY(pageContext.getCurrentY() - SECTION_SPACING);
                        }
                    } else if (pageContext.getCurrentY() - chapterHeight < PAGE_MARGIN + MIN_PAGE_HEIGHT) {
                        pageContext.newPage();
                    }

                    // 绘制章节标题
                    float chapterEndY = drawWrappedText(pageContext, chineseFont, 20, PAGE_MARGIN,
                            pageContext.getCurrentY(), pageContext.getPageWidth() - 2 * PAGE_MARGIN - SAFETY_MARGIN,
                            chapterText, true);
                    pageContext.setCurrentY(chapterEndY - CHAPTER_SPACING);

                    for (int i = 0; i < tempList.size(); i++) {
                        SysWhitePaperOutlineVo whitePaperOutlineVo = tempList.get(i);
                        if (whitePaperOutlineVo == null) {
                            continue;
                        }

                        String title = whitePaperOutlineVo.getTitle();
                        if (title == null) {
                            title = "未命名标题";
                        }
                        String content = whitePaperOutlineVo.getFianlAnalyseResult();
                        if (content == null) {
                            content = "";
                        }

                        // 检查小节标题是否需要新页面
                        String titleText = (i + 1) + "、" + title;
                        float titleHeight = estimateTextHeight(chineseFont, 16, titleText,
                                pageContext.getPageWidth() - 2 * PAGE_MARGIN - 20 - SAFETY_MARGIN) + TITLE_SPACING;

                        if (pageContext.getCurrentY() - titleHeight < PAGE_MARGIN + MIN_PAGE_HEIGHT) {
                            pageContext.newPage();
                        }

                        // 绘制小节标题
                        float titleEndY = drawWrappedText(pageContext, chineseFont, 16, PAGE_MARGIN + 20,
                                pageContext.getCurrentY(), pageContext.getPageWidth() - 2 * PAGE_MARGIN - 20 - SAFETY_MARGIN,
                                titleText, false);
                        pageContext.setCurrentY(titleEndY - TITLE_SPACING);

                        // 检查内容是否需要新页面 - 这里只检查第一行是否能放下
                        float firstLineHeight = 12 * LINE_HEIGHT;
                        if (pageContext.getCurrentY() - firstLineHeight < PAGE_MARGIN + MIN_PAGE_HEIGHT) {
                            pageContext.newPage();
                        }

                        // 绘制内容（会自动处理分页）
                        float contentEndY = drawContentWithPageBreak(pageContext, chineseFont, 12, PAGE_MARGIN + 40,
                                pageContext.getCurrentY(), pageContext.getPageWidth() - 2 * PAGE_MARGIN - 40 - SAFETY_MARGIN,
                                content);
                        pageContext.setCurrentY(contentEndY - CONTENT_SPACING);
                    }

                    chapterIndex++;
                }
            } finally {
                pageContext.close();
            }

            document.save(baos);
            return baos.toByteArray();
        }
    }

    /**
     * 页面上下文类，管理页面状态
     */
    private static class PageContext {
        private final PDDocument document;
        private PDPage currentPage;
        private PDPageContentStream contentStream;
        private float currentY;
        private final float pageWidth;
        private final float pageHeight;

        public PageContext(PDDocument document) throws IOException {
            this.document = document;
            this.currentPage = new PDPage();
            document.addPage(currentPage);
            this.contentStream = new PDPageContentStream(document, currentPage);
            this.pageWidth = currentPage.getMediaBox().getWidth();
            this.pageHeight = currentPage.getMediaBox().getHeight();
            this.currentY = pageHeight - PAGE_MARGIN;
        }

        public void newPage() throws IOException {
            contentStream.close();
            currentPage = new PDPage();
            document.addPage(currentPage);
            contentStream = new PDPageContentStream(document, currentPage);
            currentY = pageHeight - PAGE_MARGIN;
        }

        public void close() throws IOException {
            if (contentStream != null) {
                contentStream.close();
            }
        }

        public PDPageContentStream getContentStream() {
            return contentStream;
        }

        public float getCurrentY() {
            return currentY;
        }

        public void setCurrentY(float currentY) {
            this.currentY = currentY;
        }

        public float getPageWidth() {
            return pageWidth;
        }

        public float getPageHeight() {
            return pageHeight;
        }
    }

    /**
     * 处理内容分页 - 优化版本
     * 如果内容超过当前页面，先在当前页面绘制尽可能多的内容，剩余部分在下一页绘制
     */
    private float drawContentWithPageBreak(PageContext pageContext, PDFont font, float fontSize,
                                           float startX, float startY, float maxWidth, String content) throws IOException {
        if (content == null || content.trim().isEmpty()) {
            return startY;
        }

        List<String> lines = splitTextIntoLines(content, font, fontSize, maxWidth);
        float lineHeight = fontSize * LINE_HEIGHT;
        float currentY = startY;

        // 计算当前页面剩余可用高度
        float availableHeight = currentY - PAGE_MARGIN - MIN_PAGE_HEIGHT;

        // 计算当前页面能容纳的行数
        int linesThatFit = (int) (availableHeight / lineHeight);
        linesThatFit = Math.max(0, linesThatFit);

        if (linesThatFit < lines.size()) {
            // 内容在当前页面放不下，需要分页
            if (linesThatFit > 0) {
                // 在当前页面绘制尽可能多的行
                List<String> currentPageLines = lines.subList(0, linesThatFit);
                currentY = drawTextLines(pageContext.getContentStream(), font, fontSize, startX, currentY, currentPageLines, lineHeight);

                // 剩余行在新页面绘制
                List<String> remainingLines = lines.subList(linesThatFit, lines.size());
                if (!remainingLines.isEmpty()) {
                    pageContext.newPage();
                    currentY = pageContext.getPageHeight() - PAGE_MARGIN;

                    // 在新页面绘制剩余行
                    currentY = drawTextLines(pageContext.getContentStream(), font, fontSize, startX, currentY, remainingLines, lineHeight);
                }
            } else {
                // 当前页面一行都放不下，全部在新页面绘制
                pageContext.newPage();
                currentY = pageContext.getPageHeight() - PAGE_MARGIN;
                currentY = drawTextLines(pageContext.getContentStream(), font, fontSize, startX, currentY, lines, lineHeight);
            }
        } else {
            // 当前页面空间足够，直接绘制所有行
            currentY = drawTextLines(pageContext.getContentStream(), font, fontSize, startX, currentY, lines, lineHeight);
        }

        return currentY;
    }

    /**
     * 绘制自动换行文本
     */
    private float drawWrappedText(PageContext pageContext, PDFont font, float fontSize,
                                  float startX, float startY, float maxWidth,
                                  String text, boolean isBold) throws IOException {
        if (text == null || text.trim().isEmpty()) {
            return startY;
        }

        float actualFontSize = isBold ? fontSize * 1.1f : fontSize;
        List<String> lines = splitTextIntoLines(text, font, actualFontSize, maxWidth);

        return drawTextLines(pageContext.getContentStream(), font, actualFontSize, startX, startY, lines, actualFontSize * LINE_HEIGHT);
    }

    /**
     * 绘制文本行 - 修复间距计算问题
     */
    private float drawTextLines(PDPageContentStream contentStream, PDFont font, float fontSize,
                                float startX, float startY, List<String> lines, float lineHeight) throws IOException {
        if (lines == null || lines.isEmpty()) {
            return startY;
        }

        float currentY = startY;

        contentStream.beginText();
        contentStream.setFont(font, fontSize);
        contentStream.newLineAtOffset(startX, currentY);

        // 绘制第一行
        String firstLine = lines.get(0);
        if (firstLine != null) {
            contentStream.showText(firstLine);
        }

        // 绘制剩余行
        for (int i = 1; i < lines.size(); i++) {
            contentStream.newLineAtOffset(0, -lineHeight);
            String line = lines.get(i);
            if (line != null) {
                contentStream.showText(line);
            }
        }

        contentStream.endText();

        // 修复：正确计算文本绘制结束后的Y坐标
        return startY - (lines.size() - 1) * lineHeight;
    }

    /**
     * 估算文本高度
     */
    private float estimateTextHeight(PDFont font, float fontSize, String text, float maxWidth) throws IOException {
        if (text == null || text.isEmpty()) {
            return 0;
        }

        List<String> lines = splitTextIntoLines(text, font, fontSize, maxWidth);
        return lines.size() * fontSize * LINE_HEIGHT;
    }

    /**
     * 将文本分割为适合宽度的多行
     */
    private List<String> splitTextIntoLines(String text, PDFont font, float fontSize, float maxWidth) throws IOException {
        List<String> lines = new ArrayList<>();

        if (text == null || text.isEmpty()) {
            return lines;
        }

        String[] paragraphs = text.split("\n");

        for (String paragraph : paragraphs) {
            if (paragraph == null || paragraph.isEmpty()) {
                lines.add("");
                continue;
            }

            StringBuilder currentLine = new StringBuilder();
            float currentWidth = 0;

            for (int i = 0; i < paragraph.length(); i++) {
                char c = paragraph.charAt(i);
                String charStr = String.valueOf(c);
                float charWidth = font.getStringWidth(charStr) / 1000 * fontSize;

                if (currentWidth + charWidth > maxWidth && currentLine.length() > 0) {
                    lines.add(currentLine.toString());
                    currentLine = new StringBuilder(charStr);
                    currentWidth = charWidth;
                } else {
                    currentLine.append(charStr);
                    currentWidth += charWidth;
                }
            }

            if (currentLine.length() > 0) {
                lines.add(currentLine.toString());
            }
        }

        return lines;
    }

    private PDFont getChineseFont(PDDocument document) throws IOException {
        try {
            ClassPathResource fontResource = new ClassPathResource("fonts/SimHei.ttf");
            if (!fontResource.exists()) {
                throw new IOException("字体文件不存在: fonts/SimHei.ttf");
            }
            return PDType0Font.load(document, fontResource.getInputStream());
        } catch (Exception e) {
            throw new IOException("无法加载中文字体文件", e);
        }
    }
}
